class AS::Font
	# gx/gy glyph offsets, tx/ty texture offsets
	Metrics = Struct.new(:gx, :gy, :tx, :ty, :w, :h, :advance)
	
	attr_reader :tex, :line_skp, :ascent, :descent
	attr_reader :packed_indices
	
	def self.open(filename)
		tex = AS::RectTexture.open(filename + '.png')
		new(tex, filename + '.metrics')
	end

	def initialize(tex, metrics_filename)
		case tex
		when AS::RectTexture: sx, sy = 1, 1
		when AS::Texture: sx, sy = tex.w, tex.h
		else raise 'tex must be an AS::Texture'
		end

		@tex = tex
		load_glyphs(metrics_filename, 1.0/sx, 1.0/sy)
	end
	
	def line2ints(line)
		line.split.map{|str| str.to_i}
	end
	
	def load_glyphs(filename, sx, sy)
		glyphs = {}
		metrics = {}

		File.open(filename, 'r') do|metrics_file|
			@pad, @line_skip, @ascent, @descent = *line2ints(metrics_file.readline)
			
			for line in metrics_file do
				index, *other_metrics = *line2ints(line)
				metrics[index] = Metrics.new(*other_metrics)
				gx, gy, tx, ty, w, h, advance = *other_metrics
				
				glyphs[index] = AS::DisplayList.new{
					GL.Begin(GL::QUADS)
						GL.TexCoord((tx   -   @pad)*sx, (ty   -   @pad)*sy)
						GL.Vertex(   gx   -   @pad    ,  gy   -   @pad    )

						GL.TexCoord((tx + w + @pad)*sx, (ty   -   @pad)*sy)
						GL.Vertex(   gx + w + @pad    ,  gy   -   @pad    )

						GL.TexCoord((tx + w + @pad)*sx, (ty + h + @pad)*sy)
						GL.Vertex(   gx + w + @pad    ,  gy + h + @pad    )

						GL.TexCoord((tx   -   @pad)*sx, (ty + h + @pad)*sy)
						GL.Vertex(   gx   -   @pad    ,  gy + h + @pad    )
					GL.End
					
					GL.Translate(advance, 0, 0)
				}
			end
		end
				
		glyphs[?\n] = AS::DisplayList.new{
			GL.PopMatrix
			GL.Translate(0, -@line_skip, 0)
			GL.PushMatrix
		}
		
		glyphs[?\s] = AS::DisplayList.new{
			GL.Translate(metrics[?\s].advance, 0, 0)
		}
		
		glyphs.default = glyphs[?~]
		metrics.default = metrics[?~]
		
		@glyphs = Array.new(256){|i| glyphs[i]}
		@metrics = Array.new(256){|i| metrics[i]}
		
		@packed_indices = @glyphs.map{|glyph| glyph.list_id}.pack("I*")
	end
	
	def string_width(str)
		width = 0
		str.each_byte{|char| width += @metrics[char].advance}
		
		return width
	end
	
	def height
		@ascent - @descent
	end
	
	def render_string(string)
		GL.PushMatrix
			string.each_byte{|char| @glyphs[char].call}
		GL.PopMatrix
	end
end

AS::Font.autoload(:DefaultFont, "base/font/loadDefaultFont.rb")